#include "e2d/core/trans/TransformNode.h"
#include "e2d/core/Entity.h"

void e2d::Entity::SetTranform(const fxcc::graph::common::Transform& transform)
{
	//ztclog::info("%s set %f %f %f", m_Name.c_str(), transform.m_Position.x, transform.m_Position.y, transform.m_Position.z);

	auto& transformNode = Get<e2d::TransformNode>();
	transformNode.m_Local = transform;
}

fxcc::graph::common::Transform e2d::Entity::GetLocalTransform() 
{
	auto& transformNode = Get<e2d::TransformNode>();
	return transformNode.m_Local;
};


fxcc::graph::common::Transform e2d::Entity::GetWorldTransform() 
{
	auto& transformNode = Get<e2d::TransformNode>();
	return transformNode.m_World;
}

void e2d::TransformNode::LookAtTarget()
{
	if (m_Entity->m_Parent)
	{
		auto newWorld = m_World;
		newWorld.LookAt(m_TargetPos, glm::vec3(0, 1, 0));

		auto parentMatrix = GetParentMatrix();

		if (glm::abs(glm::determinant(parentMatrix)) < 1e-6f) {

			ztclog::info("parent matrix cannot determainant");
			return;
		}
		glm::mat4 localMatrix = glm::inverse(parentMatrix) * newWorld.GetWorld();

		m_Local.CreateFrom(localMatrix);
	}
	else
	{
		m_Local.LookAt(m_TargetPos, glm::vec3(0.01f, 0.99f, 0.01f));
	}


}

glm::mat4 e2d::TransformNode::GetWorldMatrix() const
{
	return m_World.GetWorld();
}

glm::mat4 e2d::TransformNode::GetParentMatrix() const
{
	if (m_Entity->m_Parent)
	{
		auto& transformNodeOfParent = m_Entity->m_Parent->Get<e2d::TransformNode>();
		return transformNodeOfParent.m_World.GetWorld();
	}
	else
	{
		return glm::mat4(1.f);
	}
}

void e2d::TransformNode::ResetLocalFromWorld() 
{
	auto entity = this->m_Entity;

	glm::mat4 parentMatrix = GetParentMatrix();
	glm::mat4 parentMatrixInv = glm::inverse(parentMatrix);
	m_Local.CreateFrom(parentMatrixInv * m_World.GetWorld());
}

void e2d::TransformNode::SetWorldMatrix(const glm::mat4& world)
{
	auto entity = this->m_Entity;

	if (m_Entity->m_Parent)
	{

		glm::mat4 parentMatrix = GetParentMatrix();
		glm::mat4 parentMatrixInv = glm::inverse(parentMatrix);
		m_Local.CreateFrom(parentMatrixInv * world);
	}
	else
	{
		m_Local.CreateFrom(world);

	}


}

void e2d::TransformNode::SetWorldTransform(const e2d::Transform& worldTransform)
{
	SetWorldMatrix(worldTransform.GetWorld());
}

void e2d::TransformNode::OnUpdate()
{

}

